package org.cnam.mobileShopping.dao;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.cnam.mobileShopping.bean.MList;
import org.cnam.mobileShopping.bean.Productlist;
import org.cnam.mobileShopping.controller.ProductListController;
import org.cnam.mobileShopping.sql.DbAdapter;
import org.cnam.mobileShopping.util.MobileShoppingUtils;
import org.cnam.mobileShopping.wsclient.WSClient;
import org.json.JSONException;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

/**
 * DAO permettant de manipuler les listes de courses
 * 
 * @author laurent
 * 
 */
public class ListeDAO extends DAO<MList> {

	private static final String tableName = "mList";

	public ListeDAO(Context context) {
		sqlHelper = new DbAdapter(context);
	}

	@Override
	public long create(MList obj) {
		// envoit du produit à la base de données distante
		// TODO Send to the web service
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getWritableDatabase();

		SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy hh:mm");
		Calendar cal = Calendar.getInstance();
		ContentValues cv = new ContentValues();
		// cv.put("mlistid", obj.getMlistid());
		cv.put("label", obj.getLabel());
		cv.put("status", obj.getStatus());
		cv.put("createdatetime", f.format(cal.getTime()));
		cv.put("commonID", obj.getCommonid());
		cv.put("version", obj.getVersion());
		cv.put("synchr", obj.isSynchr() ? 1 : 0);
		long toReturn = db.insert(tableName, "", cv);

		db.close();
		return toReturn;
	}

	@Override
	public boolean delete(MList obj) {
		// envoit du produit à la base de données distante
		// TODO Send to the web service
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getReadableDatabase();

		db.delete(tableName, "mlistid=?", new String[] { obj.getMlistid()
				.toString() });

		db.close();
		return true;
	}

	@Override
	public boolean update(MList obj) {
		// envoit du produit à la base de données distante
		// TODO Send to the web service
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getWritableDatabase();
		SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy hh:mm");
		ContentValues cv = new ContentValues();
		cv.put("mlistid", obj.getMlistid());
		cv.put("label", obj.getLabel());
		cv.put("status", obj.getStatus());
		// cv.put("createdatetime", f.format(obj.getCreatedatetime()));
		cv.put("version", obj.getVersion());
		cv.put("synchr", obj.isSynchr() ? 1 : 0);
		long toReturn = db.update(tableName, cv, "mlistid=?",
				new String[] { obj.getMlistid().toString() });

		db.close();
		return true;
	}

	@Override
	public MList find(int id) {
		MList toReturn = null;
		// TODO faire l'accès à la base de données via WebServices
		// toReturn = WebServiceController.getProduit(id);
		// <Mock Data>
		// toReturn = new Product();
		// </Mock Data>
		// envoit du produit à la base de données distante
		// TODO Send to the web service
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getReadableDatabase();

		SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy hh:mm");

		Cursor cursor = db.query(tableName, new String[] { "mlistid", "label",
				"status", "createdatetime", "commonid", "version", "synchr" },
				"mlistid=?", new String[] { String.valueOf(id) }, null, null,
				null, null);
		if (cursor.moveToFirst()) {
			do {
				toReturn = new MList();
				toReturn.setMlistid(cursor.getInt(0));
				toReturn.setLabel(cursor.getString(1));
				toReturn.setStatus(Short.valueOf(cursor.getString(2)));
				try {
					toReturn.setCreatedatetime(f.parse(cursor.getString(3)));
				} catch (ParseException e) {
					e.printStackTrace();
					toReturn.setCreatedatetime(new Date());
				}
				toReturn.setCommonid(cursor.getString(4));
				toReturn.setVersion(cursor.getInt(cursor.getInt(5)));
				toReturn.setSynchr(cursor.getInt(6) == 1 ? true : false);
			} while (cursor.moveToNext());
		}
		if (cursor != null && !cursor.isClosed()) {
			cursor.close();
		}
		db.close();
		return toReturn;
	}

	@Override
	public List<MList> findAll() {
		List<MList> toReturn = new ArrayList<MList>();
		// TODO faire l'accès à la base de données via WebServices
		// toReturn = WebServiceController.getProduit(id);
		// <Mock Data>
		// toReturn = new Product();
		// </Mock Data>
		// envoit du produit à la base de données distante
		// TODO Send to the web service
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getReadableDatabase();

		SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy hh:mm");

		Cursor cursor = db.query(tableName, new String[] { "mlistid", "label",
				"status", "createdatetime", "version", "commonid", "synchr" },
				"", null, null, null, null);
		if (cursor.moveToFirst()) {
			do {
				MList l = new MList();
				l.setMlistid(cursor.getInt(0));
				l.setLabel(cursor.getString(1));
				l.setStatus(Short.valueOf(cursor.getString(2)));
				try {
					l.setCreatedatetime(f.parse(cursor.getString(3)));
				} catch (ParseException e) {
					e.printStackTrace();
					l.setCreatedatetime(new Date());
				}
				l.setVersion(cursor.getInt(4));
				l.setCommonid(cursor.getString(5));
				l.setSynchr(cursor.getInt(6) == 1 ? true : false);
				toReturn.add(l);
			} while (cursor.moveToNext());
		}
		if (cursor != null && !cursor.isClosed()) {
			cursor.close();
		}
		db.close();
		return toReturn;
	}

	@Override
	public void synchronise(Date lastupdate, Integer userId, Context context) {

		if (MobileShoppingUtils.isConnected(context)) {
			// on appelle le serveur pour savoir si les liste ont changé
			try {
				List<MList> listsOnServer = WSClient.getInstance()
						.getListsForUser(userId);
				List<String> commonIdsLocal = new ArrayList<String>();
				// on fait une liste d'id des listes locales
				for (MList l : findAll()) {
					commonIdsLocal.add(l.getCommonid());
				}
				// synchronisation server- local on parcourt la liste
				if (listsOnServer != null) {
					MobileShoppingUtils.addSharedPref(context, "updatedLists",
							"");
					for (MList lOnServer : listsOnServer) {
						String idList = "";
						if (commonIdsLocal.contains(lOnServer.getCommonid())) {
							// la liste est présente en local
							MList listLocal = findByCommonId(lOnServer
									.getCommonid());
							if (lOnServer.getVersion() > listLocal.getVersion()) {
								idList = listLocal.getMlistid().toString();
								// la liste sur le serveur est plus récente
								// on update
								listLocal.setLabel(lOnServer.getLabel());
								listLocal.setStatus(lOnServer.getStatus());
								listLocal.setVersion(lOnServer.getVersion());
								listLocal.setSynchr(true);
								update(listLocal);
							}

							// on récupère les produits de la liste sur le
							// serveur
							List<Productlist> productlistOnServer = WSClient
									.getInstance().getProductList(
											lOnServer.getCommonid());
							if (productlistOnServer != null) {
								for (Productlist plOnServer : productlistOnServer) {
									Productlist plLocal = DAOFactory
											.getProductListDAO(context)
											.findByCommonId(
													plOnServer.getCommonid());
									if (plLocal != null) {
										// le produitlist est présent dans la
										// liste
										if (plOnServer.getVersion() > plLocal
												.getVersion()) {
											idList = listLocal.getMlistid()
													.toString();
											// le produitlist sur le server est
											// plus
											// récent
											// on le met à jour
											plLocal.setQuantity(plOnServer
													.getQuantity());
											plLocal.setStatusid(plOnServer
													.getStatusid());
											plLocal.setVersion(plOnServer
													.getVersion());
											plLocal.setSynchr(true);
											DAOFactory.getProductListDAO(
													context).update(plLocal);
										}
									} else {
										idList = listLocal.getMlistid()
												.toString();
										// le produclist n'est pas présent
										// on le rajoute
										plOnServer.setMlistid(listLocal
												.getMlistid());
										DAOFactory.getProductListDAO(context)
												.create(plOnServer);
									}

								}
							}
						} else {
							// la liste n'est pas présente, on la créé
							lOnServer.setSynchr(true);
							Long id = create(lOnServer);
							idList = id.toString();

							// on récupère les produits de la liste sur le
							// serveur
							List<Productlist> productlistOnServer = WSClient
									.getInstance().getProductList(
											lOnServer.getCommonid());
							if (productlistOnServer != null) {
								for (Productlist plOnServer : productlistOnServer) {
									// on rajoute le produclist en local
									plOnServer.setSynchr(true);
									plOnServer.setMlistid(id.intValue());
									DAOFactory.getProductListDAO(context)
											.create(plOnServer);
								}
							}
						}
						// ok là on vient de mettre à jour une liste donc on va
						// mettre en place une notification pour l'utilisateur
						// pour ce faire, comme on a pas accès au thread
						// graphique
						// on va inscrire les listes dans des sharedPreferences
						// donc on récupère la valeur et on concatène avec ","
						String updatedLists = MobileShoppingUtils
								.getSharedPreferences(context, "updatedLists",
										"");
						updatedLists += "," + idList;
						MobileShoppingUtils.addSharedPref(context,
								"updatedLists", updatedLists);
					}
				}
				// synchronisation local-server
				for (MList l : findAll()) {
					if (WSClient.getInstance().getList(l.getCommonid()) == null) {
						// la liste existe qu'en local
						// on cree la liste sur le serveur distant
						WSClient.getInstance().addList(l, 1);
						// on recupere la liste des produits en local
						List<Productlist> pls = ProductListController
								.findByList(context, l.getMlistid());
						if (pls != null) {
							// la liste a des produits associés
							// on cree les produits list sur le serveur
							for (Productlist pl : pls) {
								WSClient.getInstance().addProductInList(
										l.getCommonid(), pl, 1);
							}
						}
					} else {
						// la liste existe deja
						// on verifie que tous les produits sont presents dans
						// la
						// liste sur le server
						List<Productlist> pls = ProductListController
								.findByList(context, l.getMlistid());
						List<Productlist> plsOnServer = WSClient.getInstance()
								.getProductList(l.getCommonid());
						List<String> commonPlsInServer = new ArrayList<String>();
						if (plsOnServer != null) {
							for (Productlist plOnServer : plsOnServer) {
								commonPlsInServer.add(plOnServer.getCommonid());
							}
						}
						for (Productlist pl : pls) {
							if (!commonPlsInServer.contains(pl.getCommonid())) {
								// le produit liste n'est pas présent sur le
								// server
								// on le cree
								WSClient.getInstance().addProductInList(
										l.getCommonid(), pl, 1);
							}
						}
					}
				}
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public MList findByCommonId(String commonid) {
		MList toReturn = null;
		// récupération d'un produit dans la base de données locale
		SQLiteDatabase db = sqlHelper.getReadableDatabase();

		SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy hh:mm");

		Cursor cursor = db
				.query(tableName, new String[] { "mlistid", "label", "status",
						"createdatetime", "version", "commonid", "synchr" },
						"commonid=?", new String[] { commonid }, null, null,
						null, null);
		if (cursor.moveToFirst()) {
			do {
				toReturn = new MList();
				toReturn.setMlistid(cursor.getInt(0));
				toReturn.setLabel(cursor.getString(1));
				toReturn.setStatus(Short.valueOf(cursor.getString(2)));
				try {
					toReturn.setCreatedatetime(f.parse(cursor.getString(3)));
				} catch (ParseException e) {
					e.printStackTrace();
					toReturn.setCreatedatetime(new Date());
				}
				toReturn.setVersion(cursor.getInt(4));
				toReturn.setCommonid(cursor.getString(5));
				toReturn.setSynchr(cursor.getInt(6) == 1 ? true : false);
			} while (cursor.moveToNext());
		}
		if (cursor != null && !cursor.isClosed()) {
			cursor.close();
		}
		db.close();
		return toReturn;
	}
}
